package uk.ac.lkl.lpp.ui;



import java.awt.BorderLayout;

import java.util.HashMap;
import java.util.Map;

import javax.swing.*;

import uk.ac.lkl.common.associator.Associator;
import uk.ac.lkl.common.associator.AssociatorHandle;

import uk.ac.lkl.common.ui.ContextualisedViewCreator;

import uk.ac.lkl.lpp.PedagogyPlan;

import uk.ac.lkl.lpp.model.ldo.event.AssociatorPedagogyPlanEvent;
import uk.ac.lkl.lpp.model.ldo.event.PedagogyPlanAdapter;
import uk.ac.lkl.lpp.model.PedagogyPlanModel;


/**
 * The main linking tab.
 * 
 * This in turn consists of a set of tabs, one for each associator in the given
 * PedagogyPlan.
 * 
 * This class updates its set of tabs in line with the PedagogyPlan itself.
 * 
 * It only does this if it has an explicit view creator for a given class.
 * 
 * @author Darren Pearce
 * @version $Revision$
 * @version $Date$
 * 
 */
public class LinkingSetPanel extends JPanel {

    private static final long serialVersionUID = 1L;


    public static final String LINKINGSET_PANEL_KEY = "LinkingSetPanel";


    private PedagogyPlan plan;


    private JTabbedPane pane;


    private Map<AssociatorHandle, LinkingPanel> tabMap;


    /**
     * A map from class to corresponding view creator to use.
     * 
     * At present, no way to change what see on a per-tab basis.
     * 
     */
    private HashMap<Class, ContextualisedViewCreator> viewCreatorMap;


    /**
     * Takes a copy of the passed map.
     * 
     * Needs view creators at construction time so can generate tabs as
     * appropriate.
     * 
     * @param plan
     * @param viewCreatorMap
     */
    public LinkingSetPanel(PedagogyPlan plan,
            HashMap<Class, ContextualisedViewCreator> viewCreatorMap) {
        this.plan = plan;
        pane = new JTabbedPane();
        tabMap = new HashMap<AssociatorHandle, LinkingPanel>();
        this.viewCreatorMap = new HashMap<Class, ContextualisedViewCreator>();
        this.viewCreatorMap.putAll(viewCreatorMap);
        createTabs();
        addListener();
        setLayout(new BorderLayout(1, 1));
        // add(Messages.getJButton(LINKINGSET_PANEL_KEY,true),
        // BorderLayout.NORTH);
        add(pane, BorderLayout.CENTER);
    }


    public <O> void setViewCreatorMapping(Class<O> cl,
                                          ContextualisedViewCreator<O, PedagogyPlan> viewCreator) {
        viewCreatorMap.put(cl, viewCreator);
    }


    public void unsetViewCreatorMapping(Class cl) {
        viewCreatorMap.remove(cl);

    }


    private void createTabs() {
        Map<AssociatorHandle, Associator> associatorMap = plan.getModel()
                .getAssociatorMap();
        for (Map.Entry<AssociatorHandle, Associator> entry : associatorMap
                .entrySet()) {
            AssociatorHandle handle = entry.getKey();
            Associator associator = entry.getValue();
            if (handle.getUIIndex() > 0) {
            	addLinkingPanel(handle, associator);
            }
        }
    }


    private void addListener() {
        plan.getModel().addListener(new PedagogyPlanAdapter() {

            public void associatorAdded(AssociatorPedagogyPlanEvent e) {
                processAssociatorAdded(e);
            }


            public void associatorRemoved(AssociatorPedagogyPlanEvent e) {
                processAssociatorRemoved(e);
            }
        });
    }


    private void processAssociatorAdded(AssociatorPedagogyPlanEvent e) {
        AssociatorHandle handle = e.getHandle();
        Associator associator = e.getAssociator();
        addLinkingPanel(handle, associator);
    }


    private <S, A, D> void addLinkingPanel(AssociatorHandle handle,
                                           Associator<S, A, D> associator) {
        Class<S> sourceClass = (Class<S>) handle.getLeftListClass();
        Class<A> annotationClass = (Class<A>) handle.getAnnotationClass();
        Class<D> destinationClass = (Class<D>) handle.getRightListClass();

        ContextualisedViewCreator<S, PedagogyPlan> sourceViewCreator = viewCreatorMap
                .get(sourceClass);
        ContextualisedViewCreator<D, PedagogyPlan> destinationViewCreator = viewCreatorMap
                .get(destinationClass);

        // todo: make this do something more sensible
        if (sourceViewCreator == null || destinationViewCreator == null)
            return;

        LinkingPanel<S, A, D> linkingPanel = new LinkingPanel<S, A, D>(
                sourceClass, destinationClass, annotationClass, associator,
                sourceViewCreator, destinationViewCreator);
        PedagogyPlanModel model = plan.getModel();
        String sourceConcept = model.getConcept(sourceClass);
        String destinationConcept = model.getConcept(destinationClass);

        linkingPanel.setCreateSourceButtonLabel(sourceConcept);
        linkingPanel.setCreateDestinationButtonLabel(destinationConcept);
        pane.addTab(sourceConcept + " <-> " + destinationConcept, null, 
        		linkingPanel, "Link "+sourceConcept + " to " + destinationConcept);
        tabMap.put(handle, linkingPanel);
    }


    private void processAssociatorRemoved(AssociatorPedagogyPlanEvent e) {
        // todo: remove the relevant tab
    }
}
